// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#nullable disable

using System.Globalization;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;

namespace Microsoft.AspNetCore.StaticWebAssets.Tasks;

public partial class StaticWebAssetsManifest
{
    public class ReferencedProjectConfiguration
    {
        internal static ReferencedProjectConfiguration Create(string identity, string source) => new()
        {
            Identity = identity,
            Source = source
        };

        public string Identity { get; set; }

        public int Version { get; set; }

        public string Source { get; set; }

        public string GetPublishAssetsTargets { get; set; }

        public string AdditionalPublishProperties { get; set; }

        public string AdditionalPublishPropertiesToRemove { get; set; }

        public string GetBuildAssetsTargets { get; set; }

        public string AdditionalBuildProperties { get; set; }

        public string AdditionalBuildPropertiesToRemove { get; set; }

        public override bool Equals(object obj) => obj is ReferencedProjectConfiguration reference
            && Identity == reference.Identity
            && Version == reference.Version
            && Source == reference.Source
            && GetBuildAssetsTargets == reference.GetBuildAssetsTargets
            && AdditionalBuildProperties == reference.AdditionalBuildProperties
            && AdditionalBuildPropertiesToRemove == reference.AdditionalBuildPropertiesToRemove
            && GetPublishAssetsTargets == reference.GetPublishAssetsTargets
            && AdditionalPublishProperties == reference.AdditionalPublishProperties
            && AdditionalPublishPropertiesToRemove == reference.AdditionalPublishPropertiesToRemove;

        public override int GetHashCode()
        {
#if NET6_0_OR_GREATER
            var hashCode = new HashCode();
            hashCode.Add(Identity);
            hashCode.Add(Version);
            hashCode.Add(Source);
            hashCode.Add(GetBuildAssetsTargets);
            hashCode.Add(AdditionalBuildProperties);
            hashCode.Add(AdditionalBuildPropertiesToRemove);
            hashCode.Add(GetPublishAssetsTargets);
            hashCode.Add(AdditionalPublishProperties);
            hashCode.Add(AdditionalPublishPropertiesToRemove);

            return hashCode.ToHashCode();
#else
            var hashCode = -868952447;
            hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Identity);
            hashCode = hashCode * -1521134295 + EqualityComparer<int>.Default.GetHashCode(Version);
            hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Source);
            hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(GetBuildAssetsTargets);
            hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(AdditionalBuildProperties);
            hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(AdditionalBuildPropertiesToRemove);
            hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(GetPublishAssetsTargets);
            hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(AdditionalPublishProperties);
            hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(AdditionalPublishPropertiesToRemove);
            return hashCode;
#endif
        }

        public ITaskItem ToTaskItem()
        {
            var result = new TaskItem(Identity);

            result.SetMetadata(nameof(Version), Version.ToString(CultureInfo.InvariantCulture));
            result.SetMetadata(nameof(Source), Source);
            result.SetMetadata(nameof(GetBuildAssetsTargets), GetBuildAssetsTargets);
            result.SetMetadata(nameof(AdditionalBuildProperties), AdditionalBuildProperties);
            result.SetMetadata(nameof(AdditionalBuildPropertiesToRemove), AdditionalBuildPropertiesToRemove);
            result.SetMetadata(nameof(GetPublishAssetsTargets), GetPublishAssetsTargets);
            result.SetMetadata(nameof(AdditionalPublishProperties), AdditionalPublishProperties);
            result.SetMetadata(nameof(AdditionalPublishPropertiesToRemove), AdditionalPublishPropertiesToRemove);

            return result;
        }

        internal static ReferencedProjectConfiguration FromTaskItem(ITaskItem arg)
        {
            var result = new ReferencedProjectConfiguration
            {
                Identity = arg.GetMetadata("FullPath"),
                Version = int.Parse(arg.GetMetadata(nameof(Version)), CultureInfo.InvariantCulture),
                Source = arg.GetMetadata(nameof(Source)),
                GetBuildAssetsTargets = arg.GetMetadata(nameof(GetBuildAssetsTargets)),
                AdditionalBuildProperties = arg.GetMetadata(nameof(AdditionalBuildProperties)),
                AdditionalBuildPropertiesToRemove = arg.GetMetadata(nameof(AdditionalBuildPropertiesToRemove)),
                GetPublishAssetsTargets = arg.GetMetadata(nameof(GetPublishAssetsTargets)),
                AdditionalPublishProperties = arg.GetMetadata(nameof(AdditionalPublishProperties)),
                AdditionalPublishPropertiesToRemove = arg.GetMetadata(nameof(AdditionalPublishPropertiesToRemove))
            };

            return result;
        }
    }
}
